﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JeuDeDames;


namespace JeuDeDames
{
    public class Ordinateur : Joueur
    {
        public int profondeurMax = 1;

        public Ordinateur(int color)
        {
            couleur = color;
            this.nom = "Josette";
            this.lesPieces = new List<Piece>();
            if (color == BLANC)
                this.monTour = true;
            else if (color == NOIR)
                this.monTour = false;
        }

        public Ordinateur(int color, int profondeurMax = 1)
        {
            this.profondeurMax = profondeurMax;
            couleur = color;
            this.nom = "Josette";
            this.lesPieces = new List<Piece>();
            if (color == BLANC)
                this.monTour = true;
            else if (color == NOIR)
                this.monTour = false;
        }

        public override void jouer(Coup coup, Damier damier)
        {
            damier.afficheDamier();
                bool aJouer = false;
                Console.Clear();
                damier.afficheDamier();
                while (!aJouer)
                {
                    if ((Damier.damier[coup.origine.position] is CaseNoire) && ((Damier.damier[coup.origine.position] as CaseNoire).piece != null) && ((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).deplacementOuMangeage(coup.origine, coup.destination) == 1)
                    {
                        ((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).seDeplacer(coup);
                        Damier.historiqueCoups.Add(coup);
                    }
                    else if (((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).deplacementOuMangeage(coup.origine, coup.destination) == 2)
                    {
                        afficheCoupsPossibles();
                        ((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).mange(coup);
                        damier.afficheDamier();
                        Damier.historiqueCoups.Add(coup);
                        this.coupsPossibles = calculCoupsPossibleQuiMangentApres(coup, damier);
                        afficheCoupsPossibles();
                        if (coupsPossibles.Count() != 0)
                        {
                            jouer(coupsPossibles[0], damier);
                        }
                    }
                    aJouer = true;
                    Damier.nbTour++;
                }
        }

        /* IA First Level Stratégie : celui qui à le plus de pion est en position de force */
        public short evaluation(Joueur j)
        {
            /*
            int nbrPieces = this.lesPieces.Count() - j.lesPieces.Count();
            return Convert.ToInt16(nbrPieces);  //le nombre de ses pièces - celles de l'adversaire. >0 si j'ai plus de pieces que l'adversaire, <0 sinon.
            */

            Joueur adverse = null;
            if (d.blanc == j)
                adverse = d.noir;
            else if (d.noir == j)
                adverse = d.blanc;
            if (d.finPartie() == j)
                return 32000 - d.nbTour;
            else if (d.finPartie() == adverse)
                return -32000 + d.nbTour;
            else
            {
                int valeurPieceIA = 0;
                int valeurPieceHU = 0;
                foreach (Piece piece in j.lesPieces)
                {
                    if (piece is Pion)
                        valeurPieceIA += 1;
                    if (piece is Dame)
                        valeurPieceIA += 3;
                }
                foreach (Piece piece in adverse.lesPieces)
                {
                    if (piece is Pion)
                        valeurPieceHU += 1;
                    if (piece is Dame)
                        valeurPieceHU += 3;
                }
                return Convert.ToInt16(valeurPieceIA - valeurPieceHU);
            }




        }

        public short minmax(Damier damier, Joueur joueur, int profondeur, ref Coup coup)
        {
            short scoreEvaluation = 0, minMax = -20;
            if (profondeur == profondeurMax || damier.finPartie() == true)
            {
                scoreEvaluation = evaluation(joueur);
            }
            else
            {
                if (this.monTour == true) //tour de l'IA
                {
                    this.calculCoupsPossibles(damier);
                    foreach (Coup unCoup in this.coupsPossibles)
                    {
                        this.jouer(unCoup, damier);
                        damier.changerTour();
                        scoreEvaluation = minmax(damier, joueur, profondeur + 1, ref coup);
                        if (scoreEvaluation > minMax)
                        {
                            minMax = scoreEvaluation;
                            if (profondeur == 0)
                            {
                                coup = unCoup;
                            }
                        }
                        damier.annulerTour(Damier.nbTour - 1);
                    }
                }
                else
                {
                    joueur.calculCoupsPossibles(damier);
                    foreach (Coup unCoup in joueur.coupsPossibles)
                    {
                        (joueur as Humain).jouerIA(unCoup, damier);
                        damier.changerTour();
                        scoreEvaluation = minmax(damier, joueur, profondeur + 1, ref coup);
                        damier.annulerTour(Damier.nbTour - 1);
                    }
                }
            }
            return scoreEvaluation;

        }
        //    /*MINMAX DE L'IA*/
        //    public short minMax(Damier damier, Joueur joueur, int profondeur, Coup coup)
        //    {
        //        damier.j1.calculCoupsPossibles();
        //        damier.j2.calculCoupsPossibles();
        //        short scoreMinmax = 0;
        //        short scoreEvaluation = 0;
        //        if (profondeur == profondeurMax || damier.finPartie() == true)
        //        {
        //            scoreEvaluation = evaluation(joueur);
        //        }

        //        else
        //        {
        //            if (joueur.couleur == BLANC)
        //            {
        //                scoreEvaluation = -32768;
        //                foreach (Coup unCoup in joueur.coupsPossibles)
        //                {
        //                    joueur.jouer(unCoup);

        //                    if (profondeur != profondeurMax)
        //                    { 
        //                        scoreEvaluation = minmax(damier, damier.j2, profondeur + 1, unCoup);

        //                        damier.j1.calculCoupsPossibles();
        //                        damier.j2.calculCoupsPossibles();
        //                    }

        //                    if(scoreEvaluation > scoreMinmax)
        //                    {
        //                        scoreMinmax = scoreEvaluation;
        //                        if (joueur is Ordinateur)
        //                        {
        //                            coup = unCoup;
        //                        }
        //                    }
        //                    damier.annulerTour(Damier.nbTour - 1);
        //                }
        //            }

        //            else if (joueur.couleur == NOIR)
        //            {
        //                scoreEvaluation = 32767;
        //                foreach (Coup unCoup in joueur.coupsPossibles)
        //                {
        //                    joueur.jouer(unCoup);

        //                    if (profondeur != profondeurMax)
        //                    {
        //                        scoreEvaluation = minmax(damier, damier.j1, profondeur + 1, unCoup);

        //                        damier.j1.calculCoupsPossibles();
        //                        damier.j2.calculCoupsPossibles();
        //                    }

        //                    if(scoreEvaluation < scoreMinmax)
        //                    {
        //                        scoreMinmax = scoreEvaluation;
        //                        if (joueur is Ordinateur)
        //                        {
        //                            coup = unCoup;
        //                        }
        //                    }
        //                    damier.annulerTour(Damier.nbTour - 1);
        //                }
        //            }                
        //        }
        //        return scoreEvaluation;
        //    }

        /*1 profondeur => IA joue + adversaire joue*/
        /*meilleurNote est initialisé avant à -999*/
        //public short minmax(Damier damier, int profondeur, ref Coup meilleurCoup, short meilleurNote)
        //{
        //    short noteTemp = 0;
        //    Joueur joueur = this;
        //    Joueur adverse = null;
        //    if (damier.j1 == joueur)
        //        adverse = damier.j2;
        //    else if (damier.j2 == joueur)
        //        adverse = damier.j1;

        //    if (profondeur == 0 || damier.finPartie() == true)
        //    {
        //        return evaluation(joueur);
        //    }
        //    else
        //    {
        //        joueur.calculCoupsPossibles();
        //        foreach (Coup unCoup1 in joueur.coupsPossibles)
        //        {
        //            joueur.jouer(unCoup1);
        //            adverse.calculCoupsPossibles();

        //            foreach (Coup unCoup2 in adverse.coupsPossibles)
        //            {
        //                adverse.jouer(unCoup2);
        //                noteTemp = minmax(damier, (profondeur - 1), ref meilleurCoup, meilleurNote);
        //                if (noteTemp > meilleurNote)
        //                {
        //                    meilleurNote = noteTemp;
        //                    meilleurCoup = unCoup1;
        //                }
        //                damier.annulerTour(unCoup2.nbTour);
        //            }
        //            damier.annulerTour(unCoup1.nbTour);
        //        }
        //        return meilleurNote;
        //    }
        //}

        /*1 profondeur => IA joue + adversaire joue*/
        /*meilleurNote est initialisé avant à -999*/
        public int minMax(Damier damier, Joueur joueur, int profondeur, ref Coup meilleurCoup, int pmax)
        {
            //Console.WriteLine("Welcome to MinMax !");
            int noteTemp = 0;
            int meilleurNote=-999;
            joueur = this;
            Joueur adverse = null;
            if (damier.j1 == joueur)
                adverse = damier.j2;
            else if (damier.j2 == joueur)
                adverse = damier.j1;

            if (profondeur == 0 || damier.finPartie() == true)
            {
                return evaluation(joueur);
            }
            else
            {
                joueur.calculCoupsPossibles(damier);
                Console.WriteLine("\nCoup Possible " + joueur.nom + ":");
                joueur.afficheCoupsPossibles();
                foreach (Coup unCoup1 in joueur.coupsPossibles)
                {
                    joueur.jouer(unCoup1, damier);
                    Console.WriteLine(unCoup1 + " joué");
                    adverse.calculCoupsPossibles(damier);

                    Console.WriteLine("\nCoup Possible " + adverse.nom + ":");
                    adverse.afficheCoupsPossibles();

                    foreach (Coup unCoup2 in adverse.coupsPossibles)
                    {
                        adverse.jouer(unCoup2, damier);
                        Console.WriteLine("\t" + unCoup2 + " joué");
                        Console.WriteLine("\t\tminMax(damier, " + this.nom + ", " + (profondeur - 1) + ", " + meilleurCoup + ", " + pmax+")");
                        noteTemp = minMax(damier, this, (profondeur - 1), ref meilleurCoup, pmax);
                        Console.WriteLine("\tnoteTemp = " + noteTemp);
                        if (noteTemp > meilleurNote)
                        {
                            meilleurNote = noteTemp;
                            if(profondeur==pmax)
                                meilleurCoup = unCoup1;
                        }
                        damier.annulerTour(unCoup2.nbTour);
                        Console.WriteLine("\n\t" + unCoup2 + " annulé");
                    }
                    damier.annulerTour(unCoup1.nbTour);
                    Console.WriteLine("\n" + unCoup1 + " annulé");
                }
                Console.WriteLine("meilleurCoup : " + meilleurCoup+" !");
                return meilleurNote;
            }
        }
    }
}
